﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Xml;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Net;
using Ionic.Utils.Zip;  //this references the open source project www.codeplex.com/dotnetzip which is also licensed under the Microsoft Public License (Ms-PL)



namespace raktajino
{

    public partial class RAKTAJINO : Form
    {
        #region Globals
        string urlHostingOptions = string.Empty;
        string urlInstallationRequirements = string.Empty;
        string urlBanner = string.Empty;
        string installingString = string.Empty;
        string installingInfo = string.Empty;
        bool isInstalling = false;
        bool showProgress = false;
        DateTime progressStartTime;
        int InstallExitCode = -1;
        bool BackgroundInstallCheck = false;
        bool sortProductTreeView = false;
        WebClient downloadclient = null;

        enum EnumInfoPanel { ProductIsAlreadyInstalled,DependencyIsMissing,InstallationCheckErrorHasOccurred,CanInstall,IsInstalling, ClearAll};

        
        BackgroundWorker wpInstallation = new BackgroundWorker();
        BackgroundWorker wpInstallRequirementsCheckforTreenode = new BackgroundWorker();
       

        DateTime LastInstallationTime = new DateTime(1965,6,21);

        XmlDocument HostingOptions = new XmlDocument();

        public Products Products = null;
        Package currentPackage = null;      //the currently product that is selected in the treeview control
        Package installingPackage = null;   //the currently installing product
        #endregion


        public RAKTAJINO()
        {
            InitializeComponent();
        }

        private void RAKTAJINO_Load(object sender, EventArgs e)
        {

            wpInstallRequirementsCheckforTreenode.WorkerSupportsCancellation = true;
            urlHostingOptions = ConfigurationSettings.AppSettings["HostingOptionsURL"];
            urlInstallationRequirements = ConfigurationSettings.AppSettings["InstallationRequirementsURL"];
            urlBanner = ConfigurationSettings.AppSettings["Banner"];
           
            try
            {
                sortProductTreeView = bool.Parse(ConfigurationSettings.AppSettings["SortProductTreeView"]);
            }
            catch
            {
                sortProductTreeView = false;
            }

            string productDescriptionURL = ConfigurationSettings.AppSettings["ProductDescriptionURL"];
            string sBackgroundInstallCheck = ConfigurationSettings.AppSettings["BackgroundInstallCheck"];
            if (sBackgroundInstallCheck != null) {
                BackgroundInstallCheck = Convert.ToBoolean(sBackgroundInstallCheck);
            }
            

            wpInstallation.DoWork += new DoWorkEventHandler(wpInstallation_DoWork);
            wpInstallation.RunWorkerCompleted += new RunWorkerCompletedEventHandler(wpInstallation_RunWorkerCompleted);
            wpInstallation.ProgressChanged += new ProgressChangedEventHandler(wpInstallation_ProgressChanged);
            wpInstallation.WorkerReportsProgress = true;
            
            wpInstallRequirementsCheckforTreenode.DoWork += new DoWorkEventHandler(wpInstallRequirementsCheckforTreenode_DoWork);
            wpInstallRequirementsCheckforTreenode.RunWorkerCompleted += new RunWorkerCompletedEventHandler(wpInstallRequirementsCheckforTreenode_RunWorkerCompleted);
            wpInstallRequirementsCheckforTreenode.ProgressChanged += new ProgressChangedEventHandler(wpInstallRequirementsCheckforTreenode_ProgressChanged);
            wpInstallRequirementsCheckforTreenode.WorkerReportsProgress = true;
            
            //populate banner
            string bannerLocation = string.Format(@"{0}\{1}", Environment.CurrentDirectory, urlBanner);
            if (File.Exists(bannerLocation))
            {
                webBrowser_banner.Navigate(new Uri(bannerLocation));
            }
            else
            {
                webBrowser_banner.DocumentText = string.Format("<html>{0}</html>", this.Name);
            }

            //populate webBrowser product description
            string productDescriptionPath = string.Format(@"{0}\{1}", Environment.CurrentDirectory, productDescriptionURL);
            if (File.Exists(productDescriptionPath))
            {
                webBrowser_product_description.Navigate(new Uri(productDescriptionPath));
            }
            else
            {
                webBrowser_product_description.DocumentText = string.Format("<html>{0}</html>", this.Name);
            }


            if (urlHostingOptions != string.Empty)
            {
                //replace strings if found in the urlHostingOptions
                if (urlHostingOptions.Contains("%language%"))
                {
                    string language = System.Globalization.CultureInfo.InstalledUICulture.Name;
                    urlHostingOptions = urlHostingOptions.Replace("%language%", language);
                }

                if (urlHostingOptions.Contains("%OS%"))
                {
                    string os = Environment.OSVersion.Version.ToString();
                    urlHostingOptions = urlHostingOptions.Replace("%OS%", os);
                }
                    

                using (XmlTextReader xr = new XmlTextReader(urlHostingOptions))
                {
                    try
                    {
                        HostingOptions.Load(xr);
                    }
                    catch (SystemException ex)
                    {
                        MessageBox.Show(ex.Message, "An error has occurred");
                    }
                }
            }


            if (HostingOptions.HasChildNodes)
            {
                Products = new Products(HostingOptions);
                if (BackgroundInstallCheck) wpInstallRequirementsCheckforTreenode.RunWorkerAsync();
                
                //fill treeview with all products
                FillTreeViewAllProducts();
            }
        }
        private void RAKTAJINO_FormClosed(object sender, FormClosedEventArgs e)
        {
            string tempSubDirectory = Environment.CurrentDirectory + "\\" + ConfigurationSettings.AppSettings["TempSubDirectory"];
            string downloadSubDirectory = Environment.CurrentDirectory + "\\" + ConfigurationSettings.AppSettings["DownloadSubDirectory"];

            try
            {
                if (Directory.Exists(tempSubDirectory)) Directory.Delete(tempSubDirectory, true);
                if (Directory.Exists(downloadSubDirectory)) Directory.Delete(downloadSubDirectory, true);
            }
            catch (SystemException ex)
            {
                MessageBox.Show(string.Format("An error ocurred during deletion of the temporary working folders:\n{0}", ex.Message), "Error");
            }
        }
        

        #region Backgroundworker functions
        void wpInstallRequirementsCheckforTreenode_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            showProgress = true;
            progressStartTime = DateTime.Now;

            foreach (Package item in Products.Packages)
            {
                if (item != null)
                {
                    //if (item.InstallationRequirements == null) item.CheckRequirements();
                    item.CheckRequirements();  //yes I want every item to be checked -> as this would make sense e.g. after an installation
                    int percentage = (i * 100) / Products.Packages.Count;
                    ProgressChangedEventArgs ProgressChangedArgs = new ProgressChangedEventArgs(percentage, e);
                    i++;
                    wpInstallRequirementsCheckforTreenode.ReportProgress(percentage, e);
                }
            }
        }
        void wpInstallRequirementsCheckforTreenode_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //Update Treeview at TabPage_all Icons at each 5 % progess
            if (e.ProgressPercentage % 5 == 0)
            {
                this.Invoke(new EventHandler(AssignAllTreeNodeIcons));
            }
            ProgressChangedEventArgs pcea = new ProgressChangedEventArgs(e.ProgressPercentage, "Checking Installation Requirements");
            timer1_Tick(this, pcea);
        }
        void wpInstallRequirementsCheckforTreenode_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            showProgress = false;
            this.Invoke(new EventHandler(AssignAllTreeNodeIcons));
        }
        void wpInstallation_DoWork(object sender, DoWorkEventArgs e)
        {
            #region Installation
            InstallAction Action = GetNextRemainingInstallAction();

            if (Action == null)
            {
                e.Cancel = true;
                return;
            }

            ProcessStartInfo startInfo = new ProcessStartInfo(Action.Command.Command);
            startInfo.Arguments = Action.Command.Arguments;

            //Is the action an unzip job - if so do the work and return.
            if (Action.Command.Command.Contains("UNZIP"))
            {
                try 
                {
                    string[] parameters = Action.Command.Arguments.Split('@');
                    if (parameters.Length < 3)
                    {
                        throw new ArgumentException (string.Format("Too few UNZIP parameters at:{0}",Action.Command.Arguments));
                    }
                    string zipfilename = parameters[1].ToString();
                    string outputfolder = parameters[2].ToString();
                    if (!File.Exists(zipfilename)) throw new ArgumentException(string.Format("Zip file {0} cannot be found!", zipfilename));
                    ZipFile zip = new ZipFile(zipfilename);
                    System.IO.FileInfo fi = new System.IO.FileInfo(zipfilename);
                    decimal size = (decimal)fi.Length;
                    int unzipedsize = 0;
                    progressStartTime = DateTime.Now;
                    showProgress = true;
                    installingString = string.Format("Unzipping: {0}", zipfilename);
                    foreach (ZipEntry entry in zip)
                    {
                        // unzip and inform the user what we are currently doing
                        int percentageCompleted = (int)((decimal)(100 / size) * unzipedsize);
                        ProgressChangedEventArgs progressChangedArgs = new ProgressChangedEventArgs(percentageCompleted, installingString);
                        timer1_Tick(this, progressChangedArgs);
                        entry.Extract(outputfolder);
                        unzipedsize += entry.CompressedSize;
                    }
                    Action.ExitCode = 0;
                    Action.ExitInfoString = "UNZIP successful.";
                    zip.Dispose();
                }
                catch (SystemException se)
                {
                    Action.ExitInfoString = string.Format("Error during unzip:\n{0}", se.Message);
                }
                finally 
                {
                    installingString = string.Empty;
                    Action.done = true;
                    e.Result = Action;
                    showProgress = false;
                    bgReqCheckbar.Visible = false;
                }
                return;
            }

            //the action is no unzip - we do have to launch another process to carry out the action
            if (Action.Command.Command.Contains("cmd.exe"))
            {
                startInfo.UseShellExecute = true;
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                startInfo.RedirectStandardError = false;
                startInfo.RedirectStandardOutput = false;
                startInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.System);
            }
            else
            {
                startInfo.UseShellExecute = false;
                startInfo.RedirectStandardError = true;
                startInfo.RedirectStandardOutput = true;
            }
            Process InstallationProcess = new Process();
            InstallationProcess.StartInfo = startInfo;

            try
            {
                InstallationProcess.Start();
                isInstalling = true;
                showProgress = true;
                installingString = string.Format("{0}", installingPackage.Name);
                progressStartTime = DateTime.Now;
                ProgressChangedEventArgs progressChangedArgs = new ProgressChangedEventArgs(0, installingString);
                while (!InstallationProcess.HasExited)
                {
                    // inform the user what we are currently doing
                    wpInstallation_ProgressChanged(this, progressChangedArgs);
                    System.Threading.Thread.Sleep(1000);
                }
                //do stuff after installation has exited
                //isInstalling = false;
                InstallExitCode = InstallationProcess.ExitCode;
                Action.ExitCode = InstallExitCode;
                installingInfo = string.Format("Exitcode: {0}\nExittime: {1}", InstallationProcess.ExitCode, InstallationProcess.ExitTime.ToLongTimeString());

            }
            //catch (Win32Exception w32ex)
            catch (SystemException se)
            {
                //MessageBox.Show(this, string.Format("Error: {0}\r\nCommand:{1}\r\nParameter:{2}", w32ex.Message, Action.Command.Command, Action.Command.Arguments), "Win32 Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Action.ExitInfoString = se.Message;
            }
            finally
            {
                Action.done = true;
                e.Result = Action;
            }
            #endregion
        }


        void wpInstallation_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // we are basically showing what we are currently doing
            string installingPackageName = e.UserState as string;


            TimeSpan ts = (DateTime.Now - progressStartTime);

            installingString = string.Format("Installing: {0} ({1:F0} s)", installingPackageName, ts.TotalSeconds);
            //installingString = string.Format("Installing: {0}", this.installingPackage.Name);
            switch (ts.Seconds % 3)
            {
                case 0:
                    installingString += " .";
                    break;
                case 1:
                    installingString += " ..";
                    break;
                case 2:
                    installingString += " ...";
                    break;
            }
            
            //timer1_Tick(this,new ProgressChangedEventArgs(e.ProgressPercentage,installingString));

        }
        void wpInstallation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            installingString = string.Empty;
            installingInfo = string.Empty;

            LastInstallationTime = DateTime.Now;


            if (e.Cancelled)
            {
                // in this case the Package has been installed during this session
                // therefore we do not get a package back and leave the installation routine

                string msg = string.Format("Error in Action. Already installed.");
                for(int i=0;i<this.installingPackage.InstallationActions.Count;i++)
                {
                    msg += "\n InstallationCommand: " + this.installingPackage.InstallationActions[i].Command.Command + this.installingPackage.InstallationActions[i].Command.Arguments;
                }
                MessageBox.Show(msg, "Install Action failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                InstallationCleanup();
                return;
            }


            // the backgroundworker gives us the result as an Installaction
            // we can determine what happend 
            InstallAction ActionJustFinished = e.Result as InstallAction;

            if (ActionJustFinished.ExitCode != 0)
            {
                string msg = string.Format("Error {0} in Action {1} {2}\n{3}", ActionJustFinished.ExitCode, ActionJustFinished.Command.Command, ActionJustFinished.Command.Arguments, ActionJustFinished.ExitInfoString);
                MessageBox.Show(msg, "Install Action failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                InstallationCleanup();
                return;
            }

            InstallAction Action = GetNextRemainingInstallAction();

            // if there is another Action
            // we start a new background thread
            // otherwise we finish with the installation routine

            if (Action != null)
            {
                //SetControlsToForInstallation(true);
                wpInstallation.RunWorkerAsync();
                return;
            }

            InstallationCleanup();


        }

        

        private void InstallationCleanup()
        {
            isInstalling = false;
            bgReqCheckbar.Visible = false;
            showProgress = false;
            SetControlsToForInstallation(false);
            //reset all actions within the installed package so that it can be installed again.
            foreach (InstallAction singleAction in this.installingPackage.InstallationActions)
            {
                singleAction.done = false;
            }

            //update requirementschecking after installation  
            if (BackgroundInstallCheck)
            {
                if (!wpInstallRequirementsCheckforTreenode.IsBusy) wpInstallRequirementsCheckforTreenode.RunWorkerAsync();
            };

        }
        #endregion


        #region helper functions
        private InstallAction GetNextRemainingInstallAction()
        {
            InstallAction Action = null;

            foreach (InstallAction singleAction in this.installingPackage.InstallationActions)
            {
                if (!singleAction.done)
                {
                    Action = singleAction;
                    break;
                }
            }
            return Action;
        }
        private void FillTreeViewAllProducts()
        {
            int index;
            TreeNode tn;

            TreeView currentTreeView = treeView_products;
            currentTreeView = treeView_products;
            currentTreeView.BeginUpdate();
            currentTreeView.Nodes.Clear();

            foreach (Package item in Products.Packages)
            {
                foreach (string category in item.CategoryList)
                {
                    TreeNode catTN = new TreeNode();
                    tn = new TreeNode(item.Name);
                    tn.Tag = item;
                    int subindex;
                    if (!currentTreeView.Nodes.ContainsKey(category))
                    {
                        catTN = currentTreeView.Nodes.Add(category);
                        catTN.Name = category;
                        index = catTN.Index;
                        subindex = catTN.Nodes.Add(tn);
                        catTN.Nodes[subindex].Name = item.Name;
                    }
                    else
                    {
                        index = currentTreeView.Nodes.IndexOfKey(category);
                        subindex = currentTreeView.Nodes[index].Nodes.Add(tn);
                        currentTreeView.Nodes[index].Nodes[subindex].Name = item.Name;
                    }

                    if (item.InstallationRequirements != null)
                    {
                        AssignTreeNodeIcon(tn);
                    }
                    else
                    {
                        tn.StateImageIndex = 5;
                    }
                }
            }
            currentTreeView.ExpandAll();
            currentTreeView.ShowPlusMinus = false;
            currentTreeView.ShowRootLines = false;
            currentTreeView.ShowLines = true;

            if (sortProductTreeView) treeView_products.Sort();
            treeView_products.EndUpdate();
        }
        private void AssignAllTreeNodeIcons(object sender, EventArgs e)
        {

            TreeView currentTreeView = null;

            switch (tabControl1.SelectedTab.Name)
            {
                case "tabPage_all":
                    currentTreeView = treeView_products;
                    break;
                case "tabPage_installed":
                    currentTreeView = treeView_installed;
                    break;
                case "tabPage_installable":
                    currentTreeView = treeView_installable;
                    break;
            }
            currentTreeView.BeginUpdate();
            foreach (TreeNode tn in currentTreeView.Nodes)
            {
                //subnoded
                if (tn.Tag == null)
                {
                    TreeNodeCollection tnCol = tn.Nodes;
                    foreach(TreeNode subTN in tnCol)
                        AssignTreeNodeIcon(subTN);
                }
            }
            currentTreeView.EndUpdate();
        }
        private static void AssignTreeNodeIcon(TreeNode tn)
        {
            Package package = (Package)tn.Tag;
            if (package.InstallationRequirements != null)
            {
                if (package.InstallationRequirements.InstallCheckRequired && package.InstallationRequirements.isValidInstallationRequirements == true)
                {
                    if (package.InstallationRequirements.InstallCheckSuccessfull)
                    {
                        tn.StateImageIndex = 0;
                        tn.ForeColor = Color.Black;
                    }
                    else
                    {
                        tn.StateImageIndex = 2;
                        tn.ForeColor = Color.Gray;
                    }
                    if (package.InstallationRequirements.ProductAlreadyInstalled)
                    {
                        tn.StateImageIndex = 3;
                        tn.ForeColor = Color.Gray;
                    }
                    
                }
                else
                {
                    tn.StateImageIndex = 5;
                    tn.ForeColor = Color.Gray;
                }
            }
            else
            {
                tn.StateImageIndex = 5;
                tn.ForeColor = Color.Gray;
            }
        }
        #endregion


        #region Control functions

        void treeView_products_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (!isInstalling)
            {
                button_install.Visible = false;
                button_install.Image = imageList_icons.Images[0];
                button_install.ImageAlign = ContentAlignment.BottomRight;
            }

            installingInfo = string.Empty;

            this.currentPackage = (Package)e.Node.Tag;

            //this should not happen - in case it does show generic page to user and leave this function
            if (this.currentPackage == null)
            {
                //string td = string.Format(@"{0}\Tigerduck.jpg", Environment.CurrentDirectory);
                Type t = typeof(raktajino.Package);
                string[] asminfo = t.Assembly.ToString().Split(",".ToCharArray());
                string text = string.Format("<H1>Currently no package selected</H1><hr/>");
                text += string.Format("<FONT style='font-size:x-small'> {0} </FONT>", asminfo[1]);
                webBrowser_product_description.DocumentText = text;
                return;
            }

            if (!string.IsNullOrEmpty(this.currentPackage.DescriptionUrl))
            {
                webBrowser_product_description.Navigate(new Uri(this.currentPackage.DescriptionUrl));
            }
            else
            {
                webBrowser_product_description.DocumentText = this.currentPackage.Displaytext;
            }


            if (BackgroundInstallCheck)
            {
                if (this.currentPackage.InstallationRequirements == null)
                {
                    this.currentPackage.CheckRequirements();
                }
                TimeSpan timesincelastInstall = (this.LastInstallationTime - this.currentPackage.InstallationRequirements.LastCheckTime);
                if (timesincelastInstall.TotalSeconds > 0) this.currentPackage.CheckRequirements();
            }
            else
            {
                this.currentPackage.CheckRequirements();
            }


            //if the Installation Requirements check failed for this package for whatever reason show this to the user and leave.
            if (!this.currentPackage.InstallationRequirements.isValidInstallationRequirements)
            {
                //CheckRequirements fails this should not happen show "?" to the user
                ShowCorrectInfoPanel(EnumInfoPanel.InstallationCheckErrorHasOccurred);
                return;
            }


            //the Installation Requirements check returned valid information - now show this to the user.
            if (this.currentPackage.InstallationRequirements.InstallCheckSuccessfull)
            {
                if (!isInstalling)
                {
                    button_install.Visible = true;
                    button_install.Image = imageList_icons.Images[1];
                    button_install.ImageAlign = ContentAlignment.BottomRight;
                }
            }

            if (this.currentPackage.InstallationRequirements.ProductAlreadyInstalled)
            {
                installingInfo = "Product is installed!\n";
                ShowCorrectInfoPanel(EnumInfoPanel.ProductIsAlreadyInstalled);
            }
            else
            {
                switch (this.currentPackage.InstallationRequirements.InstallCheckSuccessfull)
                {
                    case true:
                        installingInfo = "Product can be installed!\n";
                        ShowCorrectInfoPanel(EnumInfoPanel.CanInstall);
                        break;
                    case false:
                        installingInfo = "Product cannot be installed!\n";
                        if (!isInstalling)
                        {
                            ShowCorrectInfoPanel(EnumInfoPanel.DependencyIsMissing);
                            comboBox1.Items.Clear();
                        }

                        for (int i = 0; i < this.currentPackage.InstallationRequirements.MissingRequirements.Count; i++)
                        {
                            if (this.currentPackage.CategoryList.Count > 0)
                            {
                                for (int x = 0; x < Products.Packages.Count; x++)
                                {
                                    if (Products.Packages[x].SelfCheck == this.currentPackage.InstallationRequirements.MissingRequirements[i])
                                    {
                                        if (this.currentPackage.Name != Products.Packages[x].Name)
                                        {
                                            comboBox1.Items.Add(Products.Packages[x].Name);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
                        break;
                }
            }
        }
        private void ShowCorrectInfoPanel(EnumInfoPanel whichInfoPanel)
        {
            SuspendLayout();

            if (isInstalling)
                whichInfoPanel = EnumInfoPanel.IsInstalling;

            switch (whichInfoPanel)
            { 
                case EnumInfoPanel.CanInstall:
                    button_goto_product.Visible = false;
                    panel_dependencyinfoAll.Visible = false;
                    panel_alreadyInstalledAll.Visible = false;
                    panel_installinginfoAll.Visible = false;
                    panel_productCheckFailsAll.Visible = false;
                    button_productCheckFailsInfo.Visible = false;
                    panel_dependencyinfo.Visible = false;
                    panel_installinginfo.Visible = false;
                    panel_alreadyInstalled.Visible = false;
                    panel_productCheckFails.Visible = false;
                    button_install.Visible = true;
                    break;
                case EnumInfoPanel.DependencyIsMissing:
                    panel_productCheckFails.Visible = false;
                    panel_productCheckFailsAll.Visible = false;
                    button_productCheckFailsInfo.Visible = false;
                    panel_alreadyInstalled.Visible = false;
                    panel_alreadyInstalledAll.Visible = false;
                    panel_installinginfoAll.Visible = false;
                    panel_installinginfo.Visible = false;
                    button_goto_product.Visible = true; ;
                    panel_dependencyinfo.Visible = true;
                    panel_dependencyinfoAll.Visible = true;
                    break;
                case EnumInfoPanel.InstallationCheckErrorHasOccurred:
                    panel_alreadyInstalled.Visible = false;
                    panel_alreadyInstalledAll.Visible = false;
                    panel_dependencyinfoAll.Visible = false;
                    panel_dependencyinfo.Visible = false;
                    panel_installinginfoAll.Visible = false;
                    panel_installinginfo.Visible = false;
                    button_productCheckFailsInfo.Visible = true;
                    panel_productCheckFails.Visible = true;
                    panel_productCheckFailsAll.Visible = true;
                    button_productCheckFailsInfo.Visible = true;
                    break;
                case EnumInfoPanel.ProductIsAlreadyInstalled:
                    button_goto_product.Visible = false;
                    button_install.Visible = false;
                    panel_productCheckFailsAll.Visible = false;
                    button_productCheckFailsInfo.Visible = false;
                    panel_productCheckFails.Visible = false;
                    panel_dependencyinfoAll.Visible = false;
                    panel_dependencyinfo.Visible = false;
                    panel_installinginfoAll.Visible = false;
                    panel_installinginfo.Visible = false;
                    panel_alreadyInstalled.Visible = true;
                    panel_alreadyInstalledAll.Visible = true;
                    break;
                case EnumInfoPanel.IsInstalling:
                    button_goto_product.Visible = false;
                    button_install.Visible = false;
                    panel_productCheckFailsAll.Visible = false;
                    button_productCheckFailsInfo.Visible = false;
                    panel_productCheckFails.Visible = false;
                    panel_dependencyinfoAll.Visible = false;
                    panel_dependencyinfo.Visible = false;
                    panel_alreadyInstalled.Visible = false;
                    panel_alreadyInstalledAll.Visible = false;
                    panel_installinginfo.Visible = true;
                    panel_installinginfoAll.Visible = true;
                    break;
                case EnumInfoPanel.ClearAll:
                    button_goto_product.Visible = false;
                    button_install.Visible = false;
                    panel_productCheckFailsAll.Visible = false;
                    button_productCheckFailsInfo.Visible = false;
                    panel_productCheckFails.Visible = false;
                    panel_dependencyinfoAll.Visible = false;
                    panel_dependencyinfo.Visible = false;
                    panel_alreadyInstalled.Visible = false;
                    panel_alreadyInstalledAll.Visible = false;
                    panel_installinginfo.Visible = false;
                    panel_installinginfoAll.Visible = false;
                    break;
            }
            ResumeLayout();

        }
        private void button_install_Click(object sender, EventArgs e)
        {

            if (this.currentPackage == null)
            {
                MessageBox.Show(this, "No Package selected", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //this is the package we are going to install
            this.installingPackage = this.currentPackage;

            //Eula dialog
            if (!string.IsNullOrEmpty(this.currentPackage.EulaUrl))
            {
                UserEulaDialog dlgUserEula = new UserEulaDialog();
                dlgUserEula.installingPackage = this.installingPackage;
                DialogResult dr = dlgUserEula.ShowDialog(this);

                if (dr != DialogResult.OK) return;
            }


            if (this.installingPackage.UserInput.Required)
            {
                UserInputDialog dlgUserInput = new UserInputDialog();
                dlgUserInput.installingPackage = this.installingPackage;
                DialogResult dr = dlgUserInput.ShowDialog(this);

                if (dr != DialogResult.OK) return;
            }

            this.installingPackage.GetInstallationCommand();

            SetControlsToForInstallation(true);

            //do download if necessary
            if (this.installingPackage.DownloadUrl != null)
            {
                downloadclient = new WebClient();
                downloadclient.DownloadFileCompleted += new AsyncCompletedEventHandler(downloadclient_DownloadFileCompleted);
                downloadclient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downloadclient_DownloadProgressChanged);
                string filePath = this.installingPackage.InstallationUrl + "\\" +  System.IO.Path.GetFileName(this.installingPackage.DownloadUrl.LocalPath);
                if (!Directory.Exists(Path.GetDirectoryName(filePath)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                }
                showProgress = true;
                progressStartTime = DateTime.Now;
                downloadclient.DownloadFileAsync(this.installingPackage.DownloadUrl, filePath, this.installingPackage.DownloadUrl);
            }
            else
            {
                wpInstallation.RunWorkerAsync();
            }
        }
        void downloadclient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (wpInstallRequirementsCheckforTreenode.IsBusy)
            {
                wpInstallRequirementsCheckforTreenode.CancelAsync();
            }

            installingString = string.Format("Downloading: {0} ({1}%)", ((WebClient)sender).BaseAddress, e.ProgressPercentage);
            ProgressChangedEventArgs progressChangedArgs = new ProgressChangedEventArgs(e.ProgressPercentage, installingString);
            timer1_Tick(this, progressChangedArgs);
        }
        void downloadclient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            showProgress = false;
            bgReqCheckbar.Visible = false;
            installingString = string.Empty;

            if (e.Error != null)
            {
                Uri uri = e.UserState as Uri;
                MessageBox.Show(string.Format("A download error has occurred:{0}\n{1}\nInstallation aborted", uri, e.Error.Message), "Error");
                SetControlsToForInstallation(false);
            }
            else
            { // start intstallation 
                wpInstallation.RunWorkerAsync();
            }
        }
        private void enable_button_install(object sender, EventArgs e)
        {
            button_install.Visible = !isInstalling;
            button_install.Image = null;
            treeView_products_NodeMouseClick(this, new TreeNodeMouseClickEventArgs(treeView_products.SelectedNode, MouseButtons.Left, 1, 0, 0));
        }
        private void splitContainer2_Panel2_DoubleClick(object sender, EventArgs e)
        {
            #region DEBUGHACK
#if DEBUG
            if (this.currentPackage != null)
            {


                if (this.currentPackage.UserInput.Required)
                {
                    UserInputDialog dlgUserInput = new UserInputDialog();
                    dlgUserInput.installingPackage = this.currentPackage;
                    DialogResult dr = dlgUserInput.ShowDialog(this);

                    if (dr != DialogResult.OK) return;

                }

                this.currentPackage.GetInstallationCommand();

                string msg = string.Empty;
                int i = 0;
                foreach (InstallAction singleAction in this.currentPackage.InstallationActions)
                {
                    i++;
                    msg = string.Format("Action {2}: {0} {1}", singleAction.Command.Command, singleAction.Command.Arguments, i);
                    MessageBox.Show(msg);

                }

            }
#endif
            #endregion
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (showProgress)
            {
                case true:
                    string mystring = string.Empty;
                    ProgressChangedEventArgs pcea = e as ProgressChangedEventArgs;
                    if (pcea != null)
                    {
                        mystring = pcea.UserState as string;
                        installingString = mystring;
                        if (pcea.ProgressPercentage > 0)
                        {
                            bgReqCheckbar.Value = pcea.ProgressPercentage;
                            bgReqCheckbar.Visible = true;
                        }
                        else
                        {
                            bgReqCheckbar.Visible = false;
                        }
                    }
                    else
                    {
                        mystring = installingString;
                    }
                    //TimeSpan ts = DateTime.Now - progressStartTime;
                    //mystring = string.Format("{0} ({1} s)", mystring, ts.Seconds.ToString());
                    toolStripStatusLabel_status.Text = mystring;
                    break;
                case false:
                    toolStripStatusLabel_status.Text = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
                    bgReqCheckbar.Visible = false;
                    break;
            }
      }
        private void button_goto_product_Click(object sender, EventArgs e)
        {
            //navigates to tabPage_all finds the combobox element and then selects it 
            if (comboBox1.SelectedItem != null)
            {
                tabControl1.SelectedTab = tabControl1.TabPages["tabPage_all"];

                TreeNode selectedTN = null;
                TreeNode[] foundTNCol;
                foundTNCol = treeView_products.Nodes.Find(comboBox1.SelectedItem.ToString(), true);

                if (foundTNCol != null)
                {
                    selectedTN = foundTNCol[0];
                    treeView_products.SelectedNode = selectedTN;
                    treeView_products_NodeMouseClick(this, new TreeNodeMouseClickEventArgs(selectedTN, MouseButtons.Left, 1, 0, 0));
                }
            }
        }
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //no products information could be retrieved - return
            if (Products == null) return;

            TreeView currentTreeView = null;
            int index;
            TreeNode tn;

            switch (tabControl1.SelectedTab.Name)
            {
                case "tabPage_all":
                    if (tabControl1.SelectedTab.Controls.Contains(treeView_products))
                    {   
                        //treeview found do stuff
                        currentTreeView = treeView_products;
                        currentTreeView.BeginUpdate();
                        currentTreeView.Nodes.Clear();
                        foreach (Package item in Products.Packages)
                        {
                            foreach (string category in item.CategoryList)
                            {
                                TreeNode catTN = new TreeNode();
                                tn = new TreeNode(item.Name);
                                tn.Tag = item;
                                int subindex;
                                if (!currentTreeView.Nodes.ContainsKey(category))
                                {
                                    catTN = currentTreeView.Nodes.Add(category);
                                    catTN.Name = category;
                                    index = catTN.Index;
                                    subindex = catTN.Nodes.Add(tn);
                                    catTN.Nodes[subindex].Name = item.Name;
                                }
                                else
                                {
                                    index = currentTreeView.Nodes.IndexOfKey(category);
                                    subindex = currentTreeView.Nodes[index].Nodes.Add(tn);
                                    currentTreeView.Nodes[index].Nodes[subindex].Name = item.Name;
                                }
                                AssignTreeNodeIcon(tn);
                            }
                        }
                        currentTreeView.ExpandAll();
                        currentTreeView.ShowPlusMinus = false;
                        currentTreeView.ShowRootLines = false;
                        currentTreeView.ShowLines = true;
                    }
                    break;
                case "tabPage_installed":
                    if (tabControl1.SelectedTab.Controls.Contains(treeView_installed))
                    {
                        currentTreeView = treeView_installed;
                        currentTreeView.BeginUpdate();
                        currentTreeView.Nodes.Clear();
                        foreach (Package item in Products.Packages)
                        {
                            if (item.InstallationRequirements != null)
                            {
                                if (item.InstallationRequirements.ProductAlreadyInstalled)
                                {
                                    foreach (string category in item.CategoryList)
                                    {
                                        TreeNode catTN = new TreeNode();
                                        tn = new TreeNode(item.Name);
                                        tn.Tag = item;
                                        int subindex;
                                        if (!currentTreeView.Nodes.ContainsKey(category))
                                        {
                                            catTN = currentTreeView.Nodes.Add(category);
                                            catTN.Name = category;
                                            index = catTN.Index;
                                            subindex = catTN.Nodes.Add(tn);
                                            catTN.Nodes[subindex].Name = item.Name;
                                        }
                                        else
                                        {
                                            index = currentTreeView.Nodes.IndexOfKey(category);
                                            subindex = currentTreeView.Nodes[index].Nodes.Add(tn);
                                            currentTreeView.Nodes[index].Nodes[subindex].Name = item.Name;
                                        }
                                        currentTreeView.Nodes[index].Nodes[subindex].StateImageIndex = 3;
                                    }
                                }
                            }
                        }
                        currentTreeView.ShowPlusMinus = false;
                        currentTreeView.ShowLines = true;
                        currentTreeView.ExpandAll();
                    }
                    break;

                case "tabPage_installable":
                    if (tabControl1.SelectedTab.Controls.Contains(treeView_installable))
                    {
                        currentTreeView = treeView_installable;
                        currentTreeView.BeginUpdate();
                        currentTreeView.Nodes.Clear();
                        foreach (Package item in Products.Packages)
                        {
                            if (item.InstallationRequirements != null)
                            {
                                if (item.InstallationRequirements.InstallCheckSuccessfull)
                                {
                                    foreach (string category in item.CategoryList)
                                    {
                                        TreeNode catTN = new TreeNode();
                                        tn = new TreeNode(item.Name);
                                        tn.Tag = item;
                                        int subindex;
                                        if (!currentTreeView.Nodes.ContainsKey(category))
                                        {
                                            catTN = currentTreeView.Nodes.Add(category);
                                            catTN.Name = category;
                                            index = catTN.Index;
                                            subindex = catTN.Nodes.Add(tn);
                                            catTN.Nodes[subindex].Name = item.Name;
                                        }
                                        else
                                        {
                                            index = currentTreeView.Nodes.IndexOfKey(category);
                                            subindex = currentTreeView.Nodes[index].Nodes.Add(tn);
                                            currentTreeView.Nodes[index].Nodes[subindex].Name = item.Name;
                                        }
                                        currentTreeView.Nodes[index].Nodes[subindex].StateImageIndex = 0;
                                    }
                                }
                            }
                        }
                        currentTreeView.ShowPlusMinus = true;
                        currentTreeView.ShowLines = true;
                        currentTreeView.ExpandAll();
                    }
                    break;
            }
            
            if (sortProductTreeView) currentTreeView.Sort();
            currentTreeView.EndUpdate();


            //tabControl1.SelectedTab.Controls.Add(treeView_products);
        }
        private void SetControlsToForInstallation(bool installing)
        {
            button_install.Visible = installing;

            bool disableTabControlDuringInstall = false;
            string DisableTabControlDuringInstall = ConfigurationSettings.AppSettings["DisableTabControlDuringInstall"];
            if (DisableTabControlDuringInstall != null)
            {
                disableTabControlDuringInstall = Convert.ToBoolean(DisableTabControlDuringInstall);
            }

            if (installing)
            {
                this.Cursor = Cursors.WaitCursor;
                ShowCorrectInfoPanel(EnumInfoPanel.IsInstalling);
                if (disableTabControlDuringInstall) tabControl1.Enabled = false;
            }
            else
            {
                ShowCorrectInfoPanel(EnumInfoPanel.ClearAll);
                TreeNode installedNode = treeView_products.Nodes[installingPackage.Name];
                if (installedNode != null)
                    treeView_products_NodeMouseClick(this, new TreeNodeMouseClickEventArgs(installedNode, MouseButtons.Left, 1, 0, 0));
                this.Cursor = Cursors.Default;
                tabControl1.Enabled = true;
            }
        }
        private void button_productCheckFailsInfo_Click(object sender, EventArgs e)
        {
            string details = string.Empty;

            foreach (string substr in this.currentPackage.InstallationRequirements.CheckResults)
            {
                details += substr + "\n";
            }
            MessageBox.Show(details, "Some verification check failed");
        }
        #endregion



        

    }
}
